home *** CD-ROM | disk | FTP | other *** search
- ' $Header: /sprite/src/lib/c/etc/RCS/Pdev.man,v 1.5 90/03/30 15:47:27 douglis Exp $ SPRITE (Berkeley)
- .so \*(]ltmac.sprite
- .HS Pdev lib
- .BS
- .SH NAME
- Pdev_Open, Pdev_Close, Pdev_SetDefaultHandler, Pdev_SetStreamHandler, Pdev_EnumStreams \- Package for servicing pseudo-devices.
- .SH SYNOPSIS
- \fB#include <pdev.h>\fR
- .sp
- Pdev_Token
- .br
- \fBPdev_Open\fR(\fIname, realNamePtr, reqBufSize, readBufSize, service, clientData\fR)
- .br
- void
- .br
- \fBPdev_Close\fR(\fIpdevToken\fR)
- .br
- int
- .br
- \fBPdev_GetStreamID\fR(\fIpdevToken\fR)
- .br
- int (*
- .br
- \fBPdev_SetDefaultHandler\fR(\fIpdevToken, operation, handler\fR))()
- .br
- int (*
- .br
- \fBPdev_SetStreamHandler\fR(\fIstreamPtr, operation, handler\fR))()
- .br
- int
- .br
- \fBPdev_EnumStreams\fR(\fIpdevToken, func, clientData\fR)
- .SH ARGUMENTS
- .AS Pdev_CallBacks readBufSize
- .AP char *name in
- Name of file to use for pseudo-device.
- .AP char **realNamePtr out
- Where to store pointer to actual pseudo-device file name, or NULL
- if \fIname\fR is to be the complete name of pseudo-device file.
- .AP int reqBufSize in
- The preferred size for request buffers.
- .AP int readBufSize in
- The size for a read buffer. Zero means no read buffering.
- .AP Pdev_CallBacks *service in
- A set of service call-back procedures.
- .AP ClientData clientData in
- Private user-defined data field.
- .AP Pdev_Token pdevToken in
- Token for the pseudo-device returned from \fBPdev_Open\fP.
- .AP Pdev_Stream *streamPtr in
- Handle for a stream to the pseudo-device.
- .AP int operation in
- \fBPDEV_OPEN\fP, \fBPDEV_CLOSE\fR, \fBPDEV_READ\fR, \fBPDEV_WRITE\fR,
- \fBPDEV_IOCTL\fR, \fBPDEV_SET_ATTR\fR, \fBPDEV_GET_ATTR\fR.
- .AP int (*handler)() in
- Service call-back procedure.
- .AP int (*func)() in
- A procedure applied to each stream to the pseudo-device.
- .BE
- .SH Pdev_Open
- .LP
- \fBPdev_Open\fR creates a pseudo-device
- and installs a set of service procedures for it.
- The pseudo-device can subsequently be opened by any number of
- regular (client) processes,
- and the service call-backs are made each time a client process makes
- a file system operation on the pseudo-device.
- Thus the service call-backs implement the standard file system
- operations for the pseudo-device while the Pdev package
- manages the interface between the kernel and the server process.
- .LP
- There are two ways that \fBPdev_Open\fR can pick the name of the file to
- use for the pseudo-device. If \fIrealNamePtr\fR is NULL, then
- \fBPdev_Open\fR uses \fIname\fR as the name. If \fIrealNamePtr\fR isn't
- NULL, then \fBPdev_Open\fR will generate a file name of the form
- \fIhostDir\fB/\fInameXX\fR, where \fIhostDir\fR is the name of
- a standard host-specific directory, \fIname\fR
- is the parameter to this procedure, and \fIXX\fR is a decimal number
- generated by \fBPdev_Open\fR. \fBPdev_Open\fR tries numbers up from 1 until it finds
- one that works. The name of the successful pseudo-device file is
- returned by storing a pointer to it at \fI*realNamePtr\fR; the
- storage for the name is dynamically allocated with \fBmalloc\fR and
- must eventually be freed by the caller.
- .PP
- \fBPdev_Open\fR returns an opaque token that
- is used in calls to \fBPdev_Close\fP, \fBPdev_SetDefaultHandler\fP,
- and \fBPdev_EnumStreams\fP.
- If a pseudo-device couldn't be opened, then NULL is
- returned and \fBpdev_ErrorMsg\fR contains a string
- describing the problem.
- .PP
- After a successful \fBPdev_Open\fP call the Pdev package will set up a
- \fIservice stream\fP whenever a client process
- opens the pseudo-device. Each service stream is identified
- to the call-backs by a \fBPdev_Stream\fP record.
- Thus the pseudo-device can be multiplexed over several clients
- with each client's request comming over a different service stream.
- However, forks and dups are not visible to the pseudo-device server,
- so more than one process might be using any particular service stream.
- .PP
- The \fIreqBufSize\fP is used to configure a request buffer associated
- with each service stream. This size determines how many request messages
- can be buffered before the kernel is forced to wait for them to be
- serviced. More than one request may be outstanding due to asynchronous writes,
- which are described below.
- A minimum size on the request buffer is enforced by the library,
- so zero can be passed in to get a default size (about 1 Kbyte).
- .PP
- The \fIreadBufSize\fP is used to configure an optional read buffer associated
- with each service stream. If this size is non-zero it indicates that
- a read buffer will be used to satisfy client read requests instead
- of using the read service call-back.
- In this case the Pdev package will allocate
- a read buffer each time a service stream is created and pass the address
- of this buffer to the open call-back. After that it is up to the
- server process to manage the read buffer. See the device man page
- for \fBpdev\fP for details.
- .PP
- The \fIclientData\fP parameter to \fBPdev_Open\fP
- is passed to the open call-back as
- described below. It is meant to be used as a pointer back to
- some top-level state of the pseudo-device.
- .LP
- The Pdev package uses the facilities of \fBFs_Dispatch\fR in order to keep
- track of the streams associated with the pseudo-device and ensure
- that Pdev is notified whenever those streams become readable. In order
- to use Pdev, you must also use \fBFs_Dispatch\fR.
- .SH Pdev_Close
- .LP
- \fBPdev_Close\fR shuts down a pseudo-device, closing all the streams
- associated with it and releasing any resources allocated to the
- pseudo-device. As a side-effect the close call-back is made to
- any existing service streams. After this procedure returns, \fIpdevToken\fR
- should never be used again.
- .SH Pdev_GetStreamID
- .LP
- \fBPdev_GetStreamID\fR returns the identifier for the stream
- associated with the token returned by \fBPdev_Open\fP. This may be
- used for stream-oriented calls such as \fBfstat\fP but should not be
- used as the argument to \fBclose\fP (\fBPdev_Close\fP should be used
- instead.)
- .SH "Pdev_EnumStreams"
- .PP
- The \fBPdev_EnumStreams\fP procedure is used to apply a function
- to all the service streams to the pseudo-device. This
- enumeration procedure eliminates the need to keep track of
- each service stream.
- The \fIfunc\fP argument is called on each service stream as follows:
- .DS
- int
- (*func)(streamPtr, clientData)
- Pdev_Stream *streamPtr;
- ClientData clientData;
-
- .DE
- Where \fIstreamPtr\fP identifies the service stream,
- and \fIclientData\fP is what was passed to \fBPdev_EnumStreams\fP.
- \fIfunc\fP should return zero to mean success,
- or a non-zero error status. In the case of an error
- \fBPdev_EnumStreams\fP stops its enumeration and returns the non-zero status.
- .SH "Pdev_SetDefaultHandler"
- .LP
- \fBPdev_SetDefaultHandler\fP is used to set the call-back for individual
- pdev operations.
- It is not normally needed as you can define all
- the call-backs with \fBPdev_Open\fP (or \fBPfs_OpenConnection\fP).
- The call-backs passed to \fBPdev_Open\fP are inherited by
- each service stream that is created. Changing a call-back
- with \fBPdev_SetDefaultHandler\fP changes the call-back for
- all subsequently created service streams. It doesn't affect any
- service streams that are already established.
- This returns the old default call-back.
- .SH Pdev_SetStreamHandler
- .PP
- \fBPdev_SetStreamHandler\fP is used to set a call-back for an
- already existing service stream.
- It returns the old call-back.
- .SH "SERVICE PROCEDURES"
- .ta 1.5i 3.0i 3.5i
- .PP
- The call-back service procedures are given to \fBPdev_Open\fP
- (and \fBPfs_OpenConnection\fP) as a record
- of procedures:
- .DS
- typedef struct {
- int (*open)(); /* PDEV_OPEN */
- int (*read)(); /* PDEV_READ */
- int (*write)(); /* PDEV_WRITE and PDEV_WRITE_ASYNC */
- int (*ioctl)(); /* PDEV_IOCTL */
- int (*close)(); /* PDEV_CLOSE */
- int (*getAttr)(); /* PDEV_GET_ATTR */
- int (*setAttr)(); /* PDEV_SET_ATTR */
- } Pdev_CallBacks;
- .DE
- .PP
- Any of the record elements can
- be NULL to indicate that the operation should be handled by
- a default handler.
- The \fIservice\fP parameter
- itself can also be NULL to indicate default
- handling for all operations. This is only useful during initial test.
- If a client makes an operation for which no service procedure is provided
- it is simply a no-op; it is not an error.
- The global variable \fBpdev_Trace\fP can be set to a non-zero value
- to generate printfs to stderr when
- each service procedure (default or user-supplied) is invoked.
- .LP
- Service procedures should return zero to mean successful completion,
- otherwise they should return an appropriate errno value.
- Additionally, the \fBread\fP and \fBwrite\fP procedures
- use \fBEWOULDBLOCK\fR to indicate incomplete operations.
- This is described further below.
- .LP
- Each service procedure also sets the current select state bits for
- the pseudo-device.
- The select bits are used in the kernel's implementation
- of \fBselect\fR for pseudo-devices. They should be a bitwise or
- combination of \fBFS_READABLE\fR, \fBFS_WRITABLE\fR, and \fBFS_EXCEPTION\fR.
- As well as setting this select state after each client operation,
- it may be set asynchronously with the \fBIOC_PDEV_READY\fP
- \fBioctl\fR command on the service stream.
- .PP
- These same service procedures are used for
- pseudo-device connections into the pseudo-file-system.
- See \fBPfs_Open\fP and \fBPfs_OpenConnection\fP.
- The \fBgetAttr\fP and \fBsetAttr\fP call-backs are only made to
- pseudo-file-system servers.
- For regular pseudo-devices the kernel takes care of all attribute handling.
- .SH open
- .ta 0.5i 3.0i 3.5i
- .DS
- int
- (*service->open)(clientData, streamPtr, readBuffer, flags, procID,
- hostID, uid, selectBitsPtr)
- ClientData clientData; /* Private data passed to Pdev_Open */
- Pdev_Stream *streamPtr; /* Identifies stream to pseudo-device. */
- char *readBuffer; /* Storage for optional read buffer */
- int flags; /* Flags to the open system call. NOTE!
- * These are Sprite flags defined in <fs.h>,
- * not the Unix flags defined in <sys/file.h> */
- int procID; /* ID of process opening the pseudo-device */
- int hostID; /* Host where that process is executing */
- int uid; /* User ID of that process */
- int *selectBitsPtr; /* Return - the initial select state of the process */
- .DE
- .LP
- When a client process makes an \fBopen\fP system call on the pseudo-device
- the Pdev library package invokes the \fBopen\fP service call-back to
- give the server a chance to refuse or
- accept the open by the client process. The return value of the
- open call-back is either 0 for success, or an appropriate errno value.
- .PP
- The \fBopen\fR call-back gets passed the \fIclientData\fP that was given
- to the \fBPdev_Open\fP procedure,
- and a new \fIstreamPtr\fP that is a handle on the service stream
- corresponding to the open by the client.
- \fIstreamPtr\fP is a pointer to a \fBPdev_Stream\fP
- record that contains a \fBclientData\fP field for use by the call-backs,
- and a \fBstreamID\fP field that is used in \fBioctl\fP calls
- on the service stream.
- The possible \fBioctl\fP calls are listed at the end of this man page.
- The \fIstreamPtr\fP gets passed to all the other call-backs,
- and is also passed to \fBPdev_SetStreamHandler\fP.
- .PP
- The parameters also include the
- useFlags passed to the \fBFs_Open\fP system call, and the user ID
- and Sprite hostID of the client process.
- (\fBFs_Open\fR is the Sprite version of \fBopen\fR. The
- flag bits are different and are defined in <fs.h>. Flags passed
- to \fBopen\fP are mapped to the Sprite flag bits you'll get here.)
- If the \fIreadBufSize\fP parameter to \fBPdev_Open\fP was non-zero then
- Pdev allocates \fIreadBuffer\fP and passes it to the open call-back.
- Thus there will be one read buffer for each service stream
- if the server is implementing read buffering.
- .SH close
- .ta 0.5i 3.0i 3.5i
- .DS
- int
- (*service->close)(streamPtr)
- Pdev_Stream *streamPtr; /* Identifies service stream */
- .DE
- .LP
- This is called when a service stream is closed.
- This happens either as a side effect of \fBPdev_Close\fP,
- or when the client has closed is last reference to the service stream.
- (Dups and forks are not visible to the pseudo-device server,
- so there is only one close per open system call by a client process.)
- .SH read
- .ta 0.5i 3.0i 3.5i
- .DS
- int
- (*service->read)(streamPtr, readPtr, freeItPtr, selectBitsPtr, sigPtr)
- Pdev_Stream *streamPtr; /* Identifies service stream */
- Pdev_RWParam *readPtr; /* Read parameter block */
- Boolean *freeItPtr; /* Set to TRUE if buffer should be free'd */
- int *selectBitsPtr; /* Return - select state of the pseudo-device */
- Pdev_Signal *sigPtr; /* Return - signal to generate, if any */
- .DE
- .LP
- The read service procedure is passed a record of type \fBPdev_RWParam\fP
- that indicates the \fBlength\fP, \fBoffset\fP, and \fBbuffer\fP
- for the read.
- The buffer is pre-allocated by the \fBPdev\fP library.
- If the read service procedure wants to use a different buffer
- it can change \fIreadPtr\fB->buffer\fR to reference its own storage.
- If this different storage area ought to be freed after
- the library completes the operation,
- then *\fIfreeItPtr\fR should be set to a non-zero value.
- .PP
- The \fIreadPtr\fB->length\fR record field indicates how much data is requested,
- and it should be updated to reflect the amount of data actually returned.
- If there is no data available on the pseudo-device then the
- read call-back should return \fBEWOULDBLOCK\fR
- and set \fIreadPtr\fB->length\fR to zero.
- This causes the kernel to block the client process until the select
- state of the pseudo-device is changed to indicate readability.
- If there are some bytes available the return value should be zero
- and \fIreadPtr\fB->length\fR set appropriately.
- If the read leaves no additional bytes available
- then the \fBFS_READABLE\fP bit can be cleared from *\fIselectBitsPtr\fP
- in order to block the next read request.
- End-of-file is indicated to the client by a zero return code and
- a zero number of bytes returned.
- .PP
- A signal can be generated in response to a read request by
- setting \fIsigPtr\fB->signal\fR to a non-zero value.
- \fIsigPtr\fB->code\fR can also be set to modify the signal meaning.
- Data can be returned if a signal is generated.
- The client application's system call will complete,
- its signal handler, if any, will be invoked,
- and the system call will be retried.
- .PP
- Note: If there is a read buffer associated with the service stream,
- which is indicated by a non-zero valued \fIreadBufSize\fP
- parameter to \fBPdev_Open\fP,
- then this read call-back is never called.
- Instead the kernel takes data directly
- from the read buffer. The protocol for adding data to the read buffer is
- described in the \fBpdev\fR device man page.
- .SH write
- .ta 0.5i 3.0i 3.5i
- .DS
- int
- (*service->write)(streamPtr, async, writePtr, selectBitsPtr, sigPtr)
- Pdev_Stream *streamPtr; /* Identifies service stream */
- int async; /* TRUE during an asynchronous write */
- Pdev_RWParam *writePtr; /* Write parameter block */
- int *selectBitsPtr; /* Return - select state of the pseudo-device */
- Pdev_Signal *sigPtr; /* Return - signal to generate, if any */
- .DE
- .LP
- The write service procedure is passed a parameter block that
- indicates the \fBlength\fP, \fBoffset\fP, and \fBbuffer\fP
- for the operation, plus various IDs of the application process.
- If \fIasync\fP is \fBFALSE\fP (zero)
- then \fIwritePtr\fB->length\fR should be
- updated to reflect how much data was processed by the service procedure.
- If \fIasync\fP is non-zero it indicates an asynchronous write and the service
- procedure must accept all of the data and the
- return value of \fIwritePtr\fB->length\fR is ignored.
- .PP
- If the server cannot accept all of the data it must return \fBEWOULDBLOCK\fR
- \fIand\fP update \fIwritePtr\fB->length\fR to indicate just how much data
- it accepted. This return value causes the kernel to block the client
- process until the select state of the pseudo-device is changed
- to indicate writability.
- To repeat, returning a short write count and a zero return code will cause the
- kernel to immediately issue another write request to complete
- the client's write operation.
- By also returning \fBEWOULDBLOCK\fR the pseudo-device server forces the
- client process to wait until the pseudo-device becomes writable.
- .LP
- A signal to the client application can be generated as a side effect
- by setting \fIsigPtr\fB->signal\fR to a non-zero value.
- \fIsigPtr\fB->code\fR can be set to modify the signal.
- Data can be accepted by the write service procedure if a signal is generated.
- The client application's write call will complete,
- its signal handler, if any, will be invoked,
- and the write call will be retried.
- .SH ioctl
- .ta 0.5i 3.0i 3.5i
- .DS
- int
- (*service->ioctl)(streamPtr, ioctlPtr, selectBitsPtr, sigPtr)
- Pdev_Stream *streamPtr; /* Set by open service procedure */
- Pdev_IOCParam *ioctlPtr; /* I/O Control parameter block */
- int *selectBitsPtr; /* Return - select state of pdev */
- Pdev_Signal *sigPtr; /* Return - signal to generate, if any */
- .DE
- .LP
- The ioctl service procedure takes a parameter block that specifies
- the \fBcommand\fP, and two buffers,
- one containing input data (\fBinBuffer\fP),
- and one for data returned to the client (\fBoutBuffer\fP).
- The ioctl service has to set \fIioctlPtr\fB->outBufSize\fR to indicate how much
- data is being returned to the client process.
- The \fBPdev_IOCParam\fP struct also contains various processIDs,
- and the \fBformat\fP of the host on which the client
- application is executing.
- .LP
- The pseudo-device server can implement any \fIioctlPtr\fB->command\fR it wants.
- Generic commands are defined in <fs.h>, and other ranges of commands
- for particular devices and pseudo-devices are defined in header
- files in /sprite/src/lib/include/dev.
- .LP
- The input and output data is not byteswapped by the operating system.
- It is the server's responsibility to fix up the input and output
- buffers in the case that the client has a different byte order.
- The local byte order is defined as \fBMACH_BYTE_ORDER\fR by <machparam.h>,
- and the client's byte order and alignment are
- indicated by \fIioctlPtr\fB->format\fR.
- The \fBFmt_Convert\fR library routine can be used to
- swap and align incomming and outgoing buffers.
- .LP
- A signal to the client application can be generated as a side effect
- by setting \fIsigPtr\fB->signal\fR to a non-zero value.
- \fIsigPtr\fB->code\fR can be set to modify the signal.
- .SH getAttr
- .ta 0.5i 3.0i 3.5i
- .DS
- int
- GetAttrProc(streamPtr, attrPtr, selectBitsPtr)
- Pdev_Stream *streamPtr; /* Identifies service stream */
- Fs_Attributes *attrPtr; /* Return - attributes */
- int *selectBitsPtr; /* Return - select state of the pseudo-device */
- .DE
- .LP
- This procedure is called to handle an fstat() call on a file
- in a pseudo-file system. The \fIstreamPtr\fP parameter identifies the
- open stream, and the server should fill in the attributes.
- This call-back is not made to regular pseudo-device servers,
- only to pseudo-file-system servers.
- .SH setAttr
- .ta 3.0i 3.5i
- .DS
- int
- SetAttrProc(streamPtr, flags, uid, gid, attrPtr, selectBitsPtr)
- Pdev_Stream *streamPtr; /* Identifies service stream */
- int flags; /* Indicate what attributes to set */
- int uid; /* Identifies user making the call */
- int gid; /* Identifies group of process */
- Fs_Attributes *attrPtr; /* Attributes to set as indicated by flags */
- int *selectBitsPtr; /* Return - select state of the pseudo-device */
- .DE
- .LP
- This procedure is called to set certain attributes of
- an open file in a pseudo-file system. The \fIstreamPtr\fP
- parameter identifies the open stream.
- The flags argument contains an or'd combinantion of
- \fBFS_SET_TIMES\fR, \fBFS_SET_MODE\fR, \fBFS_SET_OWNER\fR,
- \fBFS_SET_FILE_TYPE\fR, \fBFS_SET_DEVICE\fR
- that indicate what attributes to set. The attribute values are contained
- in \fI*attrPtr\fR. The \fIuid\fR and \fIgid\fR arguments
- identify the calling process.
- This call-back is not made to regular pseudo-device servers,
- only to pseudo-file-system servers.
- .SH Service Stream Ioctls
- .ta 1.0i
- .PP
- The pseudo-device server can make a few \fBFs_IOControl\fP calls on
- its service streams. The details of the calling sequences is described
- in the device man page for pseduo-devices (pdev). The possible
- operations are:
- .IP IOC_PDEV_READY
- Used to change the select state of the pseudo-device. The input buffer
- to Fs_IOControl should contain an or'd combination of
- \fBFS_READABLE\fR, \fBFS_WRITABLE\fR, or \fBFS_EXCEPTION\fR.
- .IP IOC_PDEV_SIGNAL_OWNER
- Used to send a signal to the owning process or process group of the
- pseudo-device. This is useful for implementing interrupt characters
- in tty emulators. No special permission is needed.
- .IP IOC_PDEV_WRITE_BEHIND
- Used to set or unset asynchronous writing.
- .IP IOC_PDEV_BIG_WRITES
- Used to allow or disallow writes larger than the request buffer.
- .IP IOC_PDEV_SET_PTRS
- Used to adjust pointers into the read buffer and the request buffer.
- Users of the Pdev package should only use this to adjust
- read buffer pointers. Leave the request buffer pointers equal to -1
- so you don't mess up the managing of the request buffer.
- .PP
- For example:
- .DS
- status = Fs_IOControl(streamPtr->streamID, IOC_PDEV_READY,
- sizeof(int), &selectBits, 0, NULL);
- .DE
- .SH SEE ALSO
- pdev (devices), Pfs, Swap_Buffer
- .SH KEYWORDS
- pseudo-device
-